package com.woniu.gym.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.core.exception.gym.GymException;
import com.woniu.core.exception.gym.GymExceptionCode;
import com.woniu.core.util.PageInfo;
import com.woniu.core.util.RedisKeyUtil;
import com.woniu.core.util.RedisUtil;
import com.woniu.core.util.Result;
import com.woniu.gym.client.AccountServerClient;
import com.woniu.gym.client.dto.CoachDto;
import com.woniu.gym.client.dto.CoachInfoDto;
import com.woniu.gym.client.dto.GetUserInfoByIdDTO;
import com.woniu.gym.dao.TGymBaseMapper;
import com.woniu.gym.dao.TGymCoachInfoMapper;
import com.woniu.gym.dto.GymFindCoachInfoDto;
import com.woniu.gym.dto.GymJobCoachInfoDto;
import com.woniu.gym.dto.MyFansDto;
import com.woniu.gym.dto.UserFindCoachInfoDto;
import com.woniu.gym.form.GymFindCoachInfoForm;
import com.woniu.gym.form.ModifyGymCoachInfoForm;
import com.woniu.gym.form.UserFindCoachInfoForm;
import com.woniu.gym.model.TGymBase;
import com.woniu.gym.model.TGymCoachInfo;
import com.woniu.gym.service.TGymCoachInfoService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年04月02日
 */
@Service
public class TGymCoachInfoServiceImpl extends ServiceImpl<TGymCoachInfoMapper, TGymCoachInfo> implements TGymCoachInfoService {
    @Resource
    private TGymCoachInfoMapper tGymCoachInfoMapper;
    @Resource
    private AccountServerClient accountServerClient;
    @Resource
    private TGymBaseMapper tGymBaseMapper;
    @Resource
    private RedisUtil redisUtil;
    @Override
    public List<GymJobCoachInfoDto> commentCoch(String gymNum) {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("gym_num",gymNum).eq("coach_state",1).eq("coach_type",1)
                .eq("work_state",0);
        List<TGymCoachInfo> list = tGymCoachInfoMapper.selectList(wrapper);
        ArrayList<GymJobCoachInfoDto> data = new ArrayList<>();
        for (TGymCoachInfo tGymCoachInfo : list) {
            CoachInfoDto coachInfoDto = accountServerClient.CoachInfoById(tGymCoachInfo.getCoachId()).getData();
            TGymBase tGymBase = tGymBaseMapper.selectOne(new QueryWrapper<TGymBase>().eq("gym_num",tGymCoachInfo.getGymNum()));
            GymJobCoachInfoDto dto = BeanUtil.toBean(tGymCoachInfo, GymJobCoachInfoDto.class);
            dto.setCoachName(coachInfoDto.getCoachRealname());
            dto.setGymName(tGymBase.getGymName());
            data.add(dto);

        }
        return data;
    }

    @Override
    public List<GymJobCoachInfoDto> underCoch(String gymNum) {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("gym_num",gymNum).eq("coach_state",1).eq("coach_type",2)
                .eq("work_state",0);
        List<TGymCoachInfo> list = tGymCoachInfoMapper.selectList(wrapper);
        ArrayList<GymJobCoachInfoDto> data = new ArrayList<>();
        for (TGymCoachInfo tGymCoachInfo : list) {
            CoachInfoDto coachInfoDto = accountServerClient.CoachInfoById(tGymCoachInfo.getCoachId()).getData();
            TGymBase tGymBase = tGymBaseMapper.selectOne(new QueryWrapper<TGymBase>().eq("gym_num",tGymCoachInfo.getGymNum()));
            GymJobCoachInfoDto dto = BeanUtil.toBean(tGymCoachInfo, GymJobCoachInfoDto.class);
            dto.setCoachName(coachInfoDto.getCoachRealname());
            dto.setGymName(tGymBase.getGymName());
            data.add(dto);

        }
        return data;
    }

    @Override
    public PageInfo<UserFindCoachInfoDto> userFindAllCoach(UserFindCoachInfoForm form) {
        Page<TGymCoachInfo> page = new Page<>(form.getPageNum()==null?1:form.getPageSize(),form.getPageSize()==null?5:form.getPageSize());
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_state",1);
        if(ObjectUtil.isAllNotEmpty(form.getCoachType())){
            wrapper.eq("coach_type",form.getCoachType());
        }
        if(ObjectUtil.isAllNotEmpty(form.getGymName())){
            wrapper.inSql("gym_num","SELECT gc.gym_num FROM t_gym_base gb \n" +
                    "JOIN t_gym_coach_info gc \n" +
                    "ON gb.gym_num = gc.gym_num where gb.gym_name LIKE'%"+form.getGymName()+"%'");
        }
        tGymCoachInfoMapper.selectPage(page,wrapper);
        List<TGymCoachInfo> list = page.getRecords();
        ArrayList<UserFindCoachInfoDto> data = new ArrayList<>();
        for (TGymCoachInfo tGymCoachInfo : list) {
            CoachInfoDto coachInfoDto = accountServerClient.CoachInfoById(tGymCoachInfo.getCoachId()).getData();
            TGymBase tGymBase = tGymBaseMapper.selectOne(new QueryWrapper<TGymBase>().eq("gym_num",tGymCoachInfo.getGymNum()));
            UserFindCoachInfoDto dto = BeanUtil.toBean(tGymCoachInfo, UserFindCoachInfoDto.class);
            dto.setCoachName(coachInfoDto.getCoachRealname());
            dto.setGymName(tGymBase.getGymName());
            data.add(dto);

        }
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(data);
        return pageInfo;
    }

    @Override
    public PageInfo<GymFindCoachInfoDto> gymFindAllCoach(GymFindCoachInfoForm form) {
        Page<TGymCoachInfo> page = new Page<>(form.getPageNum()==null?1:form.getPageSize(),form.getPageSize()==null?5:form.getPageSize());
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("gym_num",form.getGymNum());
        if(ObjectUtil.isAllNotEmpty(form.getCoachState())){
            wrapper.eq("coach_state",form.getCoachState());
        }
        if(ObjectUtil.isAllNotEmpty(form.getCoachType())){
            wrapper.eq("coach_type",form.getCoachType());
        }
        if(ObjectUtil.isAllNotEmpty(form.getWorkState())){
            wrapper.eq("work_state",form.getWorkState());
        }
        tGymCoachInfoMapper.selectPage(page,wrapper);
        List<TGymCoachInfo> list = page.getRecords();
        ArrayList<GymFindCoachInfoDto> data = new ArrayList<>();
        for (TGymCoachInfo tGymCoachInfo : list) {
            CoachInfoDto coachInfoDto = accountServerClient.CoachInfoById(tGymCoachInfo.getCoachId()).getData();
            TGymBase tGymBase = tGymBaseMapper.selectOne(new QueryWrapper<TGymBase>().eq("gym_num",tGymCoachInfo.getGymNum()));
            GymFindCoachInfoDto dto = BeanUtil.toBean(tGymCoachInfo, GymFindCoachInfoDto.class);
            dto.setCoachName(coachInfoDto.getCoachRealname());
            dto.setGymName(tGymBase.getGymName());
            data.add(dto);

        }
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(data);
        return pageInfo;
    }

    @Override
    public TGymCoachInfo modifyCoachNoWork(Integer coachId) {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",coachId);
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectOne(wrapper);
        if(tGymCoachInfo==null || tGymCoachInfo.getCoachState()!=1){
            throw new GymException(GymExceptionCode.COACH_NOT_EXIST);
        }
        tGymCoachInfo.setWorkState(0);
        tGymCoachInfoMapper.updateById(tGymCoachInfo);

        return tGymCoachInfo;
    }

    @Override
    public TGymCoachInfo modifyCoachHaveWork(Integer coachId) {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",coachId);
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectOne(wrapper);
        if(tGymCoachInfo==null || tGymCoachInfo.getCoachState()!=1){
            throw new GymException(GymExceptionCode.COACH_NOT_EXIST);
        }
        tGymCoachInfo.setWorkState(1);
        tGymCoachInfoMapper.updateById(tGymCoachInfo);

        return tGymCoachInfo;
    }

    @Override
    public TGymCoachInfo modifyCoachMark(Integer coachId, Double coachMark) {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",coachId);
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectOne(wrapper);
        if(tGymCoachInfo==null || tGymCoachInfo.getCoachState()!=1){
            throw new GymException(GymExceptionCode.COACH_NOT_EXIST);
        }
        // 验证评分数据
        if (coachMark < 1 || coachMark > 5) {
            throw new GymException("请输入1-5之间的评分数据",50001);
        }
        //新的评价总人数
        int num = tGymCoachInfo.getMarkNum()+1;
        //新的评分((原来的评分*原来的人数+新的评分)/新的总评价人数)
        Double newMark = (tGymCoachInfo.getCoachMark()*tGymCoachInfo.getMarkNum()+coachMark)/num;
        tGymCoachInfo.setCoachMark(newMark);
        tGymCoachInfo.setMarkNum(num);
        tGymCoachInfoMapper.updateById(tGymCoachInfo);

        return tGymCoachInfo;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public TGymCoachInfo modifyInformation(ModifyGymCoachInfoForm form) {
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectById(form.getCoachInfoId());
        if(tGymCoachInfo==null){
            throw new GymException(GymExceptionCode.INFORMATION_NOT_EXIST);
        }
        if(tGymCoachInfo.getCoachState()!=1){
            throw new GymException(GymExceptionCode.COACH_NOT_EXIST);
        }
        tGymCoachInfo.setCoachType(form.getCoachType());
        tGymCoachInfo.setCoachAdept(form.getCoachAdept());
        tGymCoachInfo.setCoachPhone(form.getCoachPhone());

        if(form.getCoachState()==2){
            tGymCoachInfo.setCoachState(form.getCoachState());
            tGymCoachInfo.setOutDate(LocalDateTime.now());
            Result<CoachDto> coachDtoResult = accountServerClient.coachUntieGym(tGymCoachInfo.getCoachId());
            if(coachDtoResult.getCode()!=200){
                throw new GymException(coachDtoResult.getMsg(),coachDtoResult.getCode());
            }
        }
        tGymCoachInfoMapper.updateById(tGymCoachInfo);



        return tGymCoachInfo;
    }

    @Override
    public GymFindCoachInfoDto follow(Integer coachId, Integer userId) throws Exception {
        QueryWrapper<TGymCoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",coachId);
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectOne(wrapper);
        if(tGymCoachInfo==null){
            throw new GymException(GymExceptionCode.INFORMATION_NOT_EXIST);
        }
        Result<GetUserInfoByIdDTO> result = accountServerClient.getUserInfoById(userId);
        if(result.getCode()!=200){
            throw new GymException(result.getMsg(),result.getCode());
        }
        //判断当前用户关注/取消关注的列表中是否存在场馆教练id
        if (redisUtil.zscore(RedisKeyUtil.followList(userId),coachId+"")!=null) {
            //存在
            //执行取消关注操作（删除该用户关注列表中的场馆教练）
            redisUtil.zrem(RedisKeyUtil.followList(userId),coachId+"");
            //拓展：取消教练粉丝
            redisUtil.zrem(RedisKeyUtil.userFollowListKey(coachId),userId+"");

            //粉丝数量-1
            redisUtil.zincrby(RedisKeyUtil.userFollowListKey(coachId),userId+"",-1.0);
            //用户关注的数量也-1
            redisUtil.zincrby(RedisKeyUtil.followList(userId),coachId+"",-1.0);
            Double number1 = redisUtil.zscore(RedisKeyUtil.followList(userId),coachId+"");
            if (number1 <= 0){
                redisUtil.zrem(RedisKeyUtil.followList(userId),coachId+"");
            }
            Double number2 = redisUtil.zscore(RedisKeyUtil.userFollowListKey(coachId),userId+"");
            if (number1 <= 0){
                redisUtil.zrem(RedisKeyUtil.userFollowListKey(coachId),userId+"");
            }

        }else {
            //关注列表中不存在该教练，执行关注操作
            double now = new Date().getTime();
            redisUtil.zadd(RedisKeyUtil.followList(userId),coachId+"",now);
            //场馆教练粉丝增加
            redisUtil.zadd(RedisKeyUtil.userFollowListKey(coachId),userId+"",now);

            //粉丝数量+1
            redisUtil.zincrby(RedisKeyUtil.followNumListKey(),coachId+"",1.0);
        }

        CoachInfoDto coachInfoDto = accountServerClient.CoachInfoById(tGymCoachInfo.getCoachId()).getData();
        TGymBase tGymBase = tGymBaseMapper.selectOne(new QueryWrapper<TGymBase>().eq("gym_num",tGymCoachInfo.getGymNum()));
        GymFindCoachInfoDto dto = BeanUtil.toBean(tGymCoachInfo, GymFindCoachInfoDto.class);
        dto.setCoachName(coachInfoDto.getCoachRealname());
        dto.setGymName(tGymBase.getGymName());
        dto.setFollowNum(redisUtil.zscore(RedisKeyUtil.followNumListKey(),coachId+""));

        return dto;
    }

    @Override
    public PageInfo<MyFansDto> myFans(Integer pageNum, Integer pageSize, Integer coachInfoId) throws Exception {
        TGymCoachInfo tGymCoachInfo = tGymCoachInfoMapper.selectById(coachInfoId);
        if(tGymCoachInfo==null){
            throw new GymException(GymExceptionCode.INFORMATION_NOT_EXIST);
        }
        pageNum = (pageNum == null) ? 1 : pageNum;
        pageSize= (pageSize == null) ? 5 : pageSize;
        //先查询收藏列表总数
        long total = redisUtil.zcard(RedisKeyUtil.userFollowListKey(tGymCoachInfo.getCoachId()));
        long pages = total%pageSize==0?total/pageSize:total/pageSize+1;
        long start = (pageNum-1)*pageSize;
        long end = pageSize*pageNum-1;
        if(redisUtil.zcard(RedisKeyUtil.userFollowListKey(tGymCoachInfo.getCoachId()))!=0){
            Set<String> set = redisUtil.zrevrange(RedisKeyUtil.userFollowListKey(tGymCoachInfo.getCoachId()), start, end);

            ArrayList<MyFansDto> data = new ArrayList<>();

            for(String userId:set){
                GetUserInfoByIdDTO tUserInfo = accountServerClient.getUserInfoById(Integer.valueOf(userId)).getData();
                MyFansDto dto = new MyFansDto();
                dto.setUserName(tUserInfo.getUserName());
                dto.setUserImage(tUserInfo.getUserImage());
                data.add(dto);
            }
            PageInfo<MyFansDto> pageInfo = new PageInfo<MyFansDto>();
            pageInfo.setTotal(total);
            pageInfo.setPages(pages);
            pageInfo.setCurrent(Long.valueOf(pageNum));
            pageInfo.setSize(Long.valueOf(pageSize));
            pageInfo.setList(data);
            return pageInfo;
        }else {
            //解决前端为null的时候控制台报错问题
            PageInfo<MyFansDto> pageInfo = new PageInfo<>();
            pageInfo.setCurrent(Long.valueOf(pageNum));
            pageInfo.setSize(Long.valueOf(pageSize));
            return pageInfo;

        }
    }
}
